package cz.cvut.fel.y36mm1.videostreaming;

import cz.cvut.fel.y36mm1.videostreaming.devicediscovery.DeviceDiscoverer;
import cz.cvut.fel.y36mm1.videostreaming.exceptions.CannotConnectToServerException;
import cz.cvut.fel.y36mm1.videostreaming.exceptions.ClientCannotBeServerException;
import cz.cvut.fel.y36mm1.videostreaming.exceptions.ServerCannotBeClientException;
import cz.cvut.fel.y36mm1.videostreaming.screens.*;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.UUID;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.midlet.*;

/**
 * This class represents a gate in our application.
 * Sets up welcome screen and allows other classes to change what is displayed
 * by calling getDisplay().setCurrent(...).
 *
 * @author Jiri Chadima, chadij1
 */
public class MainMidlet extends MIDlet implements Runnable {

    // Shared UUID by server and client
    public static final UUID RFCOMM_UUID = new UUID(0x0003);
    private Display display = null;
    private Device device = null;
    private Commander commander = null;
    private String serviceURL;
	private ErrorHandler errorHandler;

    public static final byte[] intToByteArray(int value) {
        return new byte[] { (byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value };
    }

    public static final int byteArrayToInt(byte[] b) {
        return (b[0] << 24) + ((b[1] & 0xFF) << 16) + ((b[2] & 0xFF) << 8) + (b[3] & 0xFF);
    }

    public void startApp() {
        device = new Device(this);
        commander = new Commander(this);
		errorHandler = ErrorHandler.get();
		errorHandler.setRoot(this);

        AbstractScreen welcomeScreen = new WelcomeScreen(this, "");
        display = Display.getDisplay(this);
        display.setCurrent(welcomeScreen);
        try {
            Thread.sleep(2500);
        } catch (InterruptedException ex) {
            //ex.printStackTrace();
        }
        display.setCurrent(DeviceDiscoverer.getInstance().getDevicesScreen());
        try {
            DeviceDiscoverer.getInstance().startInquiry();
            DeviceDiscoverer.getInstance().getDevicesScreen().setCommandListener(commander);
        } catch (BluetoothStateException ex) {
            ex.printStackTrace();
        // nefunguje BT, exit! TODO
        }
    }

    /**
     * start server
     */
    public void initiateServer() {
        try {
            Displayable d = device.initiateServer();
            getDisplay().setCurrent(d);
        // ukaz serverAwaitingConnectionScreen
        } catch (ClientCannotBeServerException ex) {
            errorHandler.displayError("Device cannot be server and client at the same time.", getDisplay().getCurrent());
        }

    }

	/**
	 * Stop server
	 */
    public void terminateServer() {
        try {
            device.terminateServer();
            display.setCurrent(DeviceDiscoverer.getInstance().getDevicesScreen());
        } catch (ClientCannotBeServerException ex) {
            errorHandler.displayError("Device cannot be server and client at the same time.", getDisplay().getCurrent());
        }

    }

	/**
	 * start client in new thread
	 * @param serviceURL where to connect
	 */
    public void initiateClient(String serviceURL) {
        this.serviceURL = serviceURL;

        (new Thread(this)).start();
    }

	/**
	 * Stop client
	 */
    public void terminateClient() {
        try {
            device.terminateClient();
            display.setCurrent(DeviceDiscoverer.getInstance().getDevicesScreen());
        } catch (ServerCannotBeClientException ex) {
            errorHandler.displayError("Device cannot be server and client at the same time.", getDisplay().getCurrent());
        }
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public Display getDisplay() {
        return this.display;
    }

    public Device getDevice() {
        return this.device;
    }

    public Commander getCommander() {
        return commander;
    }

	/**
	 * Client is started in new thread
	 */
    public void run() {
        try {
            Displayable d = device.initiateClient(serviceURL);
            getDisplay().setCurrent(d);
        } catch (ServerCannotBeClientException ex) {
            ErrorHandler.get().displayError("Server cannot be client in the same time!", getDisplay().getCurrent());
        } catch (CannotConnectToServerException ex) {
            ErrorHandler.get().displayError("Cannot connect to server. Restart application and try again, please.", getDisplay().getCurrent());
        }
    }
}